package cn.tedu.apiday09;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

//测试暴力反射
public class Reflex1 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
       // method();//暴力反射成员变量
       method1();//暴力反射成员方法
        //method2();//暴力反射构造方法


    }

    private static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class c = Class.forName("cn.tedu.apiday09.Person");
        //调用方法完成暴力反射
        Constructor constructor=c.getDeclaredConstructor();
        constructor.setAccessible(true);//设置私有访问可见权限
        Object o = constructor.newInstance();//自动调用无参构造
        System.out.println(o);
    }

    private static void method1() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //获取Class对象
        Class c = Person.class;
        //调用方法完成暴力反射
        //getDeclaredMethods()======可以获取类中的public和private的成员方法
        Method[] methods=c.getDeclaredMethods();
        //遍历数组，得到每一个成员方法
        for (Method m:methods
             ) {
            System.out.println(m.getName());
        }
        //调用方法暴力反射，获取一个成员方法
        //getDeclaredMethod()第一个参数是方法名，第二个参数是需要的参数类型的class的对象
        Method method = c.getDeclaredMethod("ply",int.class);
        Class[] cs = method.getParameterTypes();//获取参数类型
        System.out.println(Arrays.toString(cs));
        //执行私有方法
        //invoke()第一个参数是要执行哪个对象的方法，第二个参数是指方法要传入的具体方法值
        method.setAccessible(true);//设置私有可见,保证有足够的权限访问私有数据
        Object o = c.newInstance();
        method.invoke(o,6);



    }

    private static void method() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        //获取Class对象
        Class c = Person.class;
        //调用方法完成暴力反射
        //getDeclaredFields()====可以获取类中的public和private的成员变量
        Field[] fs = c.getDeclaredFields();
        //遍历数组，得到每一个成员变量
        for (Field f:fs
             ) {
            System.out.println(f.getName());
        }
        //调用方法暴力反射，获取一个成员变量
        Field field = c.getDeclaredField("age");
        //获取属性类型
        System.out.println(field.getType().getName());
        //给私有属性设置值set() 第一个参数是要给哪个对象设置值，第二个参数是设置具体的值
        //暴力反射的目的就是对私有的数据进行操作，但是要设置访问权限
        field.setAccessible(true);//设置私有可见
        Object o = c.newInstance();
        field.set(o,18);
        //获取私有属性的值
        System.out.println(field.get(o));
    }
}
